import { existsSync, readdirSync, readFileSync } from "fs";
import { resolve } from "path";
import { LocaleConfig } from "vitepress";
import { Versioned } from "vitepress-versioning-plugin";

import ContentSidebar from "./sidebars/content";
import { Xugu } from "./types";

function getTranslationsResolver(
  localeFolder: string,
  fileName: string,
  version: string = ""
): (key: string) => string {
  const file = resolve(
    __dirname,
    "..",
    version === "" ? "." : "versions",
    version === "" ? "." : version,
    "translated",
    localeFolder === "root" ? ".." : localeFolder,
    fileName
  );

  const strings: { [key: string]: string } = existsSync(file)
    ? JSON.parse(readFileSync(file, "utf-8"))
    : {};

  if (localeFolder === "root") {
    return (key: string) => strings[key] || key;
  } else {
    return (key: string) =>
      strings[key] || getTranslationsResolver("root", fileName, version)(key);
  }
}
export const getWebsiteResolver = (localeFolder: string, version: string) =>
  getTranslationsResolver(localeFolder, "i18n_website.json", version);
export const getSidebarResolver = (localeFolder: string, version: string) =>
  getTranslationsResolver(localeFolder, "i18n_sidebar.json", version);

export function processExistingEntries(
  sidebar: Versioned.Sidebar
): Versioned.Sidebar {
  // Get locales from __dirname/../translated/* folder names.
  const localeFolders = readdirSync(resolve(__dirname, "..", "translated"), {
    withFileTypes: true,
  })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name);

  // Get all versioning entries that match <locale>/<version>
  // aka, does not match <locale>/players or <locale>/develop or /develop or /players

  const keys = Object.keys(sidebar);
  const versionedEntries = keys.filter((key) => {
    return (
      !key.includes("/content") &&
      localeFolders.some((locale) => key.includes(locale))
    );
  });

  const versionsMet = new Set<string>();
  // Now, ensure that <locale>/<version>/players and <locale>/<version>/develop are included in the sidebar. Use <version>/players and <version>/develop as the key.
  for (const entry of versionedEntries) {
    const split = entry.split("/");
    const locale = split[1];
    const version = split[2];

    versionsMet.add(version);

    const contentToCopy = JSON.parse(
      JSON.stringify(sidebar[`/${version}/content/`])
    );

    sidebar[`/${locale}/${version}/content/`] = getLocalizedSidebar(
      contentToCopy,
      locale,
      version
    );

    // Delete the original entry.
    delete sidebar[entry];
  }

  for (const version of versionsMet) {
    sidebar[`/${version}/content/`] = getLocalizedSidebar(
      sidebar[`/${version}/content/`] as Xugu.SidebarItem[],
      "root",
      version
    );
  }

  return sidebar;
}

export function getLocalizedSidebar(
  sidebar: Xugu.SidebarItem[],
  localeCode: string,
  version: string
): Xugu.SidebarItem[] {
  const sidebarResolver = getSidebarResolver(localeCode, version);
  const localizedSidebar = JSON.parse(JSON.stringify(sidebar));

  for (const item of localizedSidebar) {
    if (item.translatable === false) {
      continue;
    }

    item.text = sidebarResolver(item.text);

    if (item.link && localeCode !== "root" && item.process !== false) {
      item.link = `/${localeCode}${item.link}`;
    }

    if (item.items) {
      item.items = getLocalizedSidebar(item.items, localeCode, version);
    }
  }

  return localizedSidebar;
}

/**
 * Generates translated sidebars for a given root directory and sidebars.
 *
 * @param sidebars - An object containing sidebars to translate, keyed by URL.
 * @param dirname - The root directory to generate translated sidebars for.
 * @returns An object containing translated sidebars, keyed by locale URL.
 */
export function generateTranslatedSidebars(
  sidebars: { [url: string]: Xugu.SidebarItem[] },
  dirname: string,
  version: string
): { [localeUrl: string]: Xugu.SidebarItem[] } {
  const translatedSidebars: { [key: string]: Xugu.SidebarItem[] } = {};

  for (const key of Object.keys(sidebars)) {
    const sidebar = sidebars[key];
    translatedSidebars[key] = getLocalizedSidebar(sidebar, "root", version);
  }

  const translatedFolder = resolve(dirname, "..", "translated");

  for (const folder of readdirSync(translatedFolder, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name)) {
    for (const key of Object.keys(sidebars)) {
      const sidebar = sidebars[key];
      translatedSidebars["/" + folder + key] = getLocalizedSidebar(
        sidebar,
        folder,
        version
      );
    }
  }

  return translatedSidebars;
}

/**
 * Generates a theme configuration for a given locale.
 *
 * @param localeCode - The code of the locale ("root" for English).
 * @returns A theme configuration object.
 */
function generateTranslatedThemeConfig(localeCode: string, version: string): Xugu.ThemeConfig {
  const websiteResolver = getWebsiteResolver(localeCode, version);

  return {
    // https://vitepress.dev/reference/default-theme-config
    logo: '/xugudb/logo.png',
    siteTitle: websiteResolver("siteTitle") +
      ' <span class="site-version">' + websiteResolver("version.display") + '</span>',
    outline: { level: [2,3], label: websiteResolver("outline") },

    nav: [
      {
        text: websiteResolver("nav.home"),
        link: "https://www.xugudb.com/"
      },
      // 由于未提供PDF文档，故注释文档下载按钮
      // {
      //   text: websiteResolver("nav.download.document"),
      //   link: '/download-pdf'
      // },
      {
        text: websiteResolver("nav.download.product"),
        link: 'https://www.xugudb.com/%e4%b8%8b%e8%bd%bd%e4%b8%ad%e5%bf%83'
      },
      { component: "VersionSwitcher" },
    ],

    lastUpdated: { text: websiteResolver("lastUpdated") },

    docFooter: {
      next: websiteResolver("docFooter.next"),
      prev: websiteResolver("docFooter.prev"),
    },

    footer: {
      copyright: websiteResolver("footer.copyright"),
    },

    darkModeSwitchLabel: websiteResolver("darkModeSwitchLabel"),
    lightModeSwitchTitle: websiteResolver("lightModeSwitchTitle"),
    darkModeSwitchTitle: websiteResolver("darkModeSwitchTitle"),
    sidebarMenuLabel: websiteResolver("sidebarMenuLabel"),
    returnToTopLabel: websiteResolver("returnToTopLabel"),
    langMenuLabel: websiteResolver("langMenuLabel"),

    search: {
      provider: "local",
      options: {
        translations: {
          button: {
            buttonText: websiteResolver("search.button.buttonText"),
            buttonAriaLabel: websiteResolver("search.button.buttonAriaLabel"),
          },
          modal: {
            displayDetails: websiteResolver("search.modal.displayDetails"),
            resetButtonTitle: websiteResolver("search.modal.resetButtonTitle"),
            backButtonTitle: websiteResolver("search.modal.backButtonTitle"),
            noResultsText: websiteResolver("search.modal.noResultsText"),
            footer: {
              selectKeyAriaLabel: websiteResolver("search.modal.footer.selectKeyAriaLabel"),
              selectText: websiteResolver("search.modal.footer.selectText"),
              navigateText: websiteResolver("search.modal.footer.navigateText"),
              navigateUpKeyAriaLabel: websiteResolver("search.modal.footer.navigateUpKeyAriaLabel"),
              navigateDownKeyAriaLabel: websiteResolver("search.modal.footer.navigateDownKeyAriaLabel"),
              closeText: websiteResolver("search.modal.footer.closeText"),
              closeKeyAriaLabel: websiteResolver("search.modal.footer.closeKeyAriaLabel"),
            },
          },
        },
      },
    },

    versionSwitcher: false,
    sidebar: generateTranslatedSidebars(
      { "/content/": ContentSidebar },
      __dirname, version
    ),

    notFound: {
      title: websiteResolver("notFound.title"),
      quote: websiteResolver("notFound.quote"),
      linkLabel: websiteResolver("notFound.linkLabel"),
      linkText: websiteResolver("notFound.linkText"),
      code: websiteResolver("notFound.code"),
    },

    version: {
      reminder: websiteResolver("version.reminder"),
      switcher: websiteResolver("version.switcher"),
      display: websiteResolver("version.display"),
    },
  };
}

/**
 * Loads locales and generates a LocaleConfig object.
 *
 * @param dirname - The root directory of the project.
 * @returns A LocaleConfig object with locales and their corresponding themeConfig.
 */
export function loadLocales(dirname: string, version: string): LocaleConfig<Xugu.ThemeConfig> {
  const translatedFolder = resolve(dirname, "..", "translated");
  const localeFolders = readdirSync(translatedFolder, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name);

  const websiteResolver = getWebsiteResolver("root", version);
  const locales: LocaleConfig<Xugu.ThemeConfig> = {
    root: {
      description: websiteResolver("description"),
      label: "🇨🇳 中文",
      lang: "zh",
      themeConfig: generateTranslatedThemeConfig("root", version),
      title: websiteResolver("title"),
    },
  };

  for (const localeCode of localeFolders) {
    const websiteResolver = getWebsiteResolver(localeCode, version);

    if (!existsSync(resolve(translatedFolder, localeCode, "index.md"))) {
      continue;
    }

    const language = localeCode.slice(0, 2);
    const region = localeCode.slice(3, 5).toUpperCase();

    const localeNameInLocale = new Intl.DisplayNames(language, {
      type: "language",
    });

    const localizedName =
      localeNameInLocale.of(language)![0].toUpperCase() +
      localeNameInLocale.of(language)!.slice(1);

    const countryFlag = String.fromCodePoint(
      ...region.split("").map((char) => 127397 + char.charCodeAt(0))
    );

    locales[localeCode] = {
      description: websiteResolver("description"),
      label: `${countryFlag} ${localizedName}`,
      lang: localeCode,
      link: `/${localeCode}/`,
      themeConfig: generateTranslatedThemeConfig(localeCode, version),
      title: websiteResolver("title"),
    };
  }

  return locales;
}
